package cn.edu.xjtu;

import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    // 需要处理的文件所在文件夹,自动检索子文件夹
    public static String basePath = "D:\\大三上";
    // 非直接上传模式照片存储路径(本地git仓库的路径)...注意:后面需要加\\
    public static String imgStorePath = "D:\\drawing-bed-two\\img\\";
    // 非直接上传模式照片上传后访问的前缀
    public static String imgUploadPrefix = "https://gitee.com/hydrogenion/drawing-bed-two/raw/master/img/";
    // 处理后的文件输出路径...注意:后面需要加\\
    public static String fileStorePath = "D:\\blogs\\笔记\\笔记汇总\\";
    // 上传文件的命令,需要再拼接文件路径,这里使用的picGo-core,也可以使用其他的上传工具
    public static String uploadCommand = "cmd /d/s/c C:\\Users\\tux\\AppData\\Roaming\\Typora\\picgo\\win64\\picgo.exe u ";
    // 需要检测的图片后缀
    public static String[] imgSuffix = {".png", "jpg", "jpeg"};

    // 换行符,写文件时候会用到
    public static byte[] newLine = "\n".getBytes();
    // img标签形式的图片正则表达式 <img src=".." alt=".." style=".." />
    public static String imgRegularExpression = ".*<img.*/>.*";
    // 正常图片链接的正则表达式 ![](.suffix)
    public static String[] normalRegularExpression = new String[imgSuffix.length];
    // 获取小括号中内容的正则表达式
    public static Pattern parenthesesPattern = Pattern.compile("\\((.*?)\\)");

    // 获取中括号中内容的正则表达式
    public static Pattern BracketPattern = Pattern.compile("\\[(.*?)]");

    /**
     * 上传模式
     * 1:调用picGo直接上传到码云
     * 2:保存到本地git仓库
     * 直接上传速度比较慢,测试处理120张照片需要2-3分钟
     * 建议如果图片量比较小时再使用模式1,否则使用模式2
     */
    public static int mode;

    static int fileCount = 0;//处理文件数量
    static int imgCount = 0;//处理图片数量

    public static void main(String[] args) {
        init();//根据imgSuffix构造normalRegularExpression正则表达式
        readInput();
        File dir = new File(basePath);

        // 判断文件夹是否存在
        if (!dir.exists()) {
            System.out.println("目录不存在");
            return;
        }
        trans(dir);

        System.out.println("共计处理了" + fileCount + "个文件");
        System.out.println("共计处理了" + imgCount + "张图片");
    }

    /**
     * 读取输入选择模式
     * 1:自动上传
     * 2:传到本地git仓库中
     */
    private static void readInput() {
        Scanner in = new Scanner(System.in);
        System.out.println("模式一自动上传\n模式二存入本地git仓库\n请输入选择的模式(1 or 2)");
        while (true) {
            mode = in.nextInt();
            if (mode == 1 || mode == 2) {
                break;
            }
            System.out.println("输入错误,请重新输入");
        }
        in.close();
    }

    /**
     * 根据imgSuffix构造normalRegularExpression正则表达式
     */
    private static void init() {
        // 判断文件输出文件夹是否存在
        File file = new File(fileStorePath);
        if (!file.exists()) {
            file.mkdirs();
        }

        // 判断照片输出文件夹是否存在
        file = new File(imgStorePath);
        if (!file.exists()) {
            file.mkdirs();
        }

        for (int i = 0; i < imgSuffix.length; i++) {
            normalRegularExpression[i] = ".*!\\[.*]\\(.*" + imgSuffix[i] + "\\).*";
            System.out.println(normalRegularExpression[i]);
        }
    }

    /**
     * 文件转换
     *
     * @param fileInput 需要处理的文件夹
     */
    public static void trans(File fileInput) {
        try {
            // 获取文件列表
            File[] fileList = fileInput.listFiles();
            assert fileList != null;
            for (File file : fileList) {
                // 递归处理文件夹
                if (file.isDirectory()) {
                    trans(file);
                } else {
                    // 需要读取的文件名称
                    String fileName = file.getName();
                    // 判断是否是.md文件,如果不是直接跳过
                    if (!fileName.endsWith(".md")) {
                        continue;
                    }
                    System.out.println(fileName);

                    InputStreamReader read = new InputStreamReader(new FileInputStream(file));
                    BufferedReader bufferedReader = new BufferedReader(read);
                    String lineText = null;

                    // 输出文件路径
                    String outputFileName = getFullName(fileInput.getAbsolutePath(), fileName);
                    String outPath = fileStorePath + "\\" + outputFileName;
                    FileOutputStream outputStream = new FileOutputStream(outPath);

                    // 按行读取文件并打印,如果需要对内容进行操作可以在这里进行
                    while ((lineText = bufferedReader.readLine()) != null) {
                        boolean flag = judgeTrans(lineText);
                        if (!flag) {
                            outputStream.write(lineText.getBytes());
                            outputStream.write(newLine);
                            continue;
                        }
                        imgCount++;// 统计照片数量

                        StringBuilder outStringBuilder = new StringBuilder();
                        String imgPath = "";
                        String imgFileName = "";

                        if (lineText.matches(imgRegularExpression)) {
                            // 获取到图片的名称以及路径
                            String[] splitArray = lineText.split("\"");
                            imgPath = splitArray[1];
                            //imgFileName = splitArray[3];
                            imgFileName = imgPath.split("/")[1];
                        } else {
                            // 获得到图片路径以及图片名称

                            // 图片名称在[]中,不太对,这里面的文件没有后缀
                            //Matcher matcher = BracketPattern.matcher(lineText);
                            //matcher.find();
                            //imgFileName = matcher.group(1);

                            // 图片路径在()中
                            Matcher matcher = parenthesesPattern.matcher(lineText);
                            matcher.find();
                            imgPath = matcher.group(1);

                            imgFileName = imgPath.split("/")[1];
                        }

                        // 如果是http开头的说明上传过该图片或者是其他链接
                        if (imgPath.startsWith("http")) {
                            outputStream.write((lineText.toString()).getBytes());
                            outputStream.write(newLine);
                            continue;
                        }

                        System.out.println(fileInput.getAbsolutePath() + "\\" + imgPath);
                        String fileUrl = getFileUrl(fileInput.getAbsolutePath() + "\\" + imgPath, imgFileName);

                        //String fileUrl = uploadImage(fileInput.getAbsolutePath() + "\\" + imgPath);
                        //outStringBuilder.append("![").append(imgFileName).append("](").append(fileUrl).append(")");

                        // 构造新名称
                        outStringBuilder.append("![").append(imgFileName).append("](").append(fileUrl).append(")");

                        // 这里考虑到部分图片可能是放在注解中,因此需要获得图片标签的前缀并将其替换得到最终的字符串
                        if (!lineText.startsWith("<img")) {
                            // System.out.println(lineText);
                            int index = lineText.indexOf("<img");
                            if (index == -1) {
                                index = lineText.indexOf("![");
                            }
                            String subString = lineText.substring(0, index);
                            outStringBuilder.insert(0, subString);
                            // System.out.println(outStringBuilder);
                        }
                        System.out.println(outStringBuilder);

                        outputStream.write((outStringBuilder.toString()).getBytes());
                        outputStream.write(newLine);
                    }
                    fileCount++;

                    // 关闭输入输出流
                    outputStream.close();
                    bufferedReader.close();
                    read.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取输出文件的名称,将其每一级路径拼接起来的到其文件名称(不包括盘符名称)
     *
     * @param absolutePath 该文件所在文件夹的绝对路径
     * @param fileName     该文件名称
     * @return 处理后的文件名称
     */
    private static String getFullName(String absolutePath, String fileName) {
        String[] strs = absolutePath.split("\\\\");
        System.out.println(Arrays.toString(strs));
        StringBuilder sb = new StringBuilder();
        if (strs.length == 1) {
            return fileName;
        }
        for (int i = 1; i < strs.length; i++) {
            sb.append(strs[i]).append("_");
        }
        return sb.toString() + fileName;
    }

    /**
     * 获得图片的路径
     * <p>
     * 如果是模式1则上传然后获取上传的路径
     * 如果是模式2则虚拟出上传后的路径,即默认访问照片的前缀加文件名
     * <p>
     * TODO:(这里可以优化,新建线程去处理上传照片的过程,将其路径直接使用模式二类似的构造方法即可,但是考虑到处理图片的量多了可能会上千张,同时建立上千个线程不知道会有什么后果,如果有大佬可以解决欢迎提pr)
     *
     * @param imgAbsPath 图片的绝对路径
     * @param fileName   图片名称
     * @return 上传后的图片路径
     */
    private static String getFileUrl(String imgAbsPath, String fileName) {
        String fileUrl = "";
        try {
            if (mode == 1) {
                fileUrl = uploadImage(imgAbsPath);
            } else {
                fileUrl = imgUploadPrefix + fileName;
                savePicToGitRepo(imgAbsPath, fileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileUrl;
    }

    /**
     * 模式2时将图片直接保存到本地git仓库
     *
     * @param imgAbsPath 图片绝对路径
     * @param fileName   图片名称
     */
    private static void savePicToGitRepo(String imgAbsPath, String fileName) {
        File file = new File(imgAbsPath);
        InputStream inputStream = null;
        OutputStream os = null;
        try {
            inputStream = new FileInputStream(file);
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            os = new FileOutputStream(imgStorePath + fileName);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 完毕，关闭所有链接
            try {
                os.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }


    /**
     * 判断该行是否需要进行格式转换
     *
     * @param text 行文字
     * @return true:需要转换,false:不需要转换
     */
    private static boolean judgeTrans(String text) {
        if (text.matches(imgRegularExpression)) {
            return true;
        }
        for (String str : normalRegularExpression) {
            if (text.matches(str)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 调用picGo-core上传照片并获取上传链接
     *
     * @param path 照片所在路径
     * @return 上传的链接
     * @throws Exception 异常
     */
    public static String uploadImage(String path) throws Exception {
        Process p = Runtime.getRuntime().exec(uploadCommand + path);
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String readLine;
        String outString = "";
        while ((readLine = br.readLine()) != null) {
            System.out.println(readLine);
            if (readLine.startsWith("https:")) {
                outString = readLine;
                //System.out.println(outString);
            }
        }
        p.destroy();
        p = null;
        return outString;
    }
}
